#pragma once
#include <core/sync/lock.h>
#include <stdint.h>

#include <map>
#include <mutex>
#include <vector>

#include "../BondInfo.h"
#include "../BondMarketStream.h"
#include "../SSVContainer.h"
#include "../bondlib.h"
#include "IRealTimeDealModel.h"

namespace detail {
class CBondDealJumpList;
class RealTimeDealCache;
class RealTimeDealStat;
class RealTimeDealList;
}  // namespace detail
struct MarkStreamListArg {
  int corp;
  int mark_type;
  int page_type;  // emMktStreamPage
  std::vector<uint32_t> days;
  MarkStreamListArg() : corp(-1), mark_type(-1), page_type(-1) {}
};
struct MarketStreamTopArg {
  int count;
  int mark_type;
  std::vector<uint32_t> days;
  MarketStreamTopArg() : count(10), mark_type(-1) {}
};
struct MarketStreamInfoArg {
  int stat_type;
  int mark_type;
  std::vector<uint32_t> days;
  MarketStreamInfoArg() : stat_type(-1), mark_type(-1) {}
};
class S_BONDLIB_EXPORT CMarketStream : public CMarketStreamBase {
  enum { OBJECT_TAG = 0xf1f2f3f4 };
  typedef int BatchId;
  typedef uint32_t DayType;

  typedef std::mutex CSLock;
  typedef std::lock_guard<std::mutex> ScopedCSLock;
  typedef std::map<DayType, int64_t> DayStateMap;

 protected:
  typedef detail::RealTimeDealList RTDealList;
  typedef std::map<DayType, RTDealList*> DayDealMap;

 public:
  typedef std::list<MarketStreamInfo> MSInfoList;
  typedef std::map<std::string, MarketStreamRec> MSRecMap;
  struct ParsedStreamInfo {
    uint32_t unDay;
    CMarketStreamBase::kStreamType type;
    MarketStreamInfo info;
  };

 public:  // 共用枚举定义已经迁移到CMarketStreamBase中
 protected:
  // 用于检测当前对象的合法性,合法对象必须是固定值
  unsigned int m_tag;

  // 用于按天保存当天的成交信息,通常是当天的成交信息最多
  DayDealMap m_deal_map;
  DayStateMap m_deal_states;

  // GetOrCreateList中用于保存上次查找结果,加快GetOrCreateList速度;
  // 如果给定day与此结果的日期相等,那么立即返回
  RTDealList* m_last;

  // 每此收到的E_FID_QB_MARKET_STREAM_DEAL_PUSH消息对应的xQBMarketStreamList_c*
  // 称为一个批次,保存到m_keys中
  // 界面中收到通知后,与此底层数据同步索引,也会更新批次id
  // 两者的批次id用于表示处理成交记录信息的各自进度
  BatchId m_nextid;
  qb::base::Mutex m_lock;

 public:
  struct EnumeratorArg {
    CMarketStream* object;
    uint32_t day;
  };
  class Enumerator;
  typedef const Enumerator* ConstEnumPtr;
  class S_BONDLIB_EXPORT iterator {
    ConstEnumPtr m_enumerator;
    int m_index;

   public:
    iterator()
        : m_enumerator(0), m_index(-1) {}  // 为了CMarketStreamDebug::iterator
    iterator(int index, ConstEnumPtr enumerator)
        : m_index(index), m_enumerator(enumerator) {}
    iterator(const iterator& it)
        : m_index(it.m_index), m_enumerator(it.m_enumerator) {}
    iterator& operator=(const iterator& it) {
      m_index = it.m_index;
      m_enumerator = it.m_enumerator;
      return *this;
    }
    const MarketStreamInfo& operator*() const;
    const MarketStreamInfo* operator->() const;
    bool operator==(const iterator& it) const {
      return m_enumerator == it.m_enumerator && m_index == it.m_index;
    }
    bool operator!=(const iterator& it) const {
      return m_index != it.m_index || m_enumerator != it.m_enumerator;
    }
    iterator& operator++() {
      m_index++;
      return *this;
    }
  };
  class S_BONDLIB_EXPORT Enumerator {
    std::vector<DealIndex> m_indexes;
    IRecordMap* m_values;
    detail::RealTimeDealStat* m_stats;
    //	ScopedCSLock		m_scoped;
    friend class iterator;

   private:
    Enumerator();
    Enumerator(const Enumerator& e);
    Enumerator& operator=(const Enumerator& e);

   public:
    explicit Enumerator(CMarketStream* object, uint32_t day, bool all = false);
    ~Enumerator() {}
    bool findrec(const std::string& combBondKey, MarketStreamRec& rec) const;
    iterator begin() const;
    iterator end() const { return iterator(m_indexes.size(), this); }

   protected:
    const MarketStreamInfo& GetAt(int nIndex) const;
  };

 public:
  static CMarketStream& cfectsStream();
  static CMarketStream& exchangeStream();
  static CMarketStream& bondStream();

  void Save() {}
  bool Clear(uint32_t uTime = 0);

 public:  // 兼容接口
  qb::base::Mutex& GetMutex() { return m_lock; }
  void RefreshKeyToContainer(CSSVContainer* pssv, char* pszCorp);

  // 获取MarketStreamInfo
  bool GetMarketStreamByKey(const char* szCombBondKey, const char* szKey,
                            MarketStreamInfo& stInfo, uint32_t timeDay = 0);
  bool GetMarketStreamByBrokers(const std::vector<BrokerKey>& brokerKeys,
                                std::vector<MarketStreamInfo>& records,
                                time_t t = 0, uint32_t day = 0);
  bool GetLastMarketStream(const std::vector<BrokerKey>& brokerKeys,
                           std::vector<MarketStreamInfo>& records, time_t t = 0,
                           uint32_t day = 0);

  bool GetMarketStreamStatByKey(const char* szCombBondKey,
                                MarketStreamRec& stat, uint32_t timeDay = 0);

  // 获取Broker对应中与时间接近的MarketStream
  bool GetNearByMarketStream(const char* pBondCombKey, time_t t,
                             const char* pBrokerId, MarketStreamInfo& info,
                             uint32_t timeDay = 0);

  // 经过调查,以下使用到了CMarketStreamlst.m_Record信息
  bool GetTFRelativeStream(CMarketStreamlst& Marketlist, uint32_t timeDay = 0);
  bool GetInterestRateStream(CMarketStreamlst& Marketlist,
                             uint32_t timeDay = 0);
  bool GetCreditRateStream(CMarketStreamlst& Marketlist, uint32_t timeDay = 0,
                           bool bNeedNCD = false /*是否含NCD*/);

  // 经过调查以下接口中并没有使用到CMarketStreamlst.m_Record信息
  bool GetLastDayMSByCorp(int nCorp, CMarketStreamlst& mktLst);

  bool GetMarketInfoByType(CMarketStreamlst& Marketlist, MarktType mkType,
                           uint32_t timeDay = 0);
  bool GetMarketInfoByType(
      CMarketStreamlst& Marketlist, MarktType mkType,
      const std::vector<uint32_t>& timeVector);  // 子窗口成交

  bool GetInterestRateStream(
      CMarketStreamlst& Marketlist,
      const std::vector<uint32_t>& timeVector);  // 利率债成交
  bool GetCreditRateStream(CMarketStreamlst& Marketlist,
                           const std::vector<uint32_t>& timeVector,
                           bool bNeedNCD = false /*是否含NCD*/);  // 信用债成交

  // 获取CMarketToprec
  // bool	GetMarketRecord(CMarketToprec &MarketInfo,uint32_t timeDay = 0);
  // bool	GetMarketActvTrans(CMarketToprec &MarketInfo,MarktType
  // mkType,uint32_t timeDay = 0);
  bool GetMarketRecord(CMarketToprec& MarketInfo,
                       const std::vector<uint32_t>& timeVector,
                       uint32_t nActvNum = 10);  // 成交概览 -- 活跃成交
  static bool GetTodayMarketRecord(CMarketToprec& MarketInfo,
                                   const CMarketStreamlst& lst,
                                   uint32_t nActvNum = 10);  // 获取当天活跃成交
  bool GetMarketActvTrans(CMarketToprec& MarketInfo, MarktType mkType,
                          const std::vector<uint32_t>& timeVector,
                          uint32_t nActvNum = 10);  // 子窗口 -- 活跃成交

  // 获取CMarketInfoMap
  bool GetMarketInfoByType(
      CMarketInfoMap& MarketInfo,
      const std::vector<uint32_t>&
          timeVector);  // 成交概览 -- 成交分布--
                        // 按新QB产品类型分类，即地方债、国债、央票、金融债、短融、中票、企业债、其他
  bool GetMarketInfoByType(CMarketInfoMap& MarketInfo, uint32_t timeDay = 0);
  bool GetMarketInfoByDate(
      CMarketInfoMap& MarketInfo,
      const std::vector<uint32_t>&
          timeVector);  // 成交概览 -- 成交分布--
                        // 每条柱为当日某一特定剩余期限范围内的所有债券成交记录的笔数
  bool GetMarketInfoByDate(CMarketInfoMap& MarketInfo, uint32_t timeDay = 0);

  bool GetMarketTransDate(
      CMarketInfoMap& MarketInfo, MarktType mkType,
      const std::vector<uint32_t>& timeVector);  // 国债 -- 成交分布
  bool GetMarketTransDate(CMarketInfoMap& MarketInfo, MarktType mkType,
                          uint32_t timeDay = 0);

  bool GetMarketRatioByType(
      CMarketInfoMap& MarketInfo, MarktType mkType,
      const std::vector<uint32_t>& timeVector);  // 其他 -- 成交分布
  bool GetMarketRatioByType(CMarketInfoMap& MarketInfo, MarktType mkType,
                            uint32_t timeDay = 0);

  bool GetMarketTransRating(
      CMarketInfoMap& MarketInfo, MarktType mkType,
      const std::vector<uint32_t>&
          timeVector);  // 短融,中票，企业债，城投债 -- 成交分布
  bool GetMarketTransRating(CMarketInfoMap& MarketInfo, MarktType mkType,
                            uint32_t timeDay = 0);

  bool GetMarketTransNFRate(
      CMarketInfoMap& MarketInfo, MarktType mkType,
      const std::vector<uint32_t>& timeVector);  // 浮息债 -- 成交分布
  bool GetMarketTransNFRate(CMarketInfoMap& MarketInfo, MarktType mkType,
                            uint32_t timeDay = 0);

 public:  // 获取成交信息,共有6大接口
  // 获取某家Broker最后一笔成交version
  int GetVersion(int companyID);

  // 用于快速获取一屏的当日实时成交信息
  int GetRecords(IRealTimeDealModel* keys, int& pos, int count, void* records);

  // 获取指定债券的单个成交信息,或者多个（GetBondDealBatch）
  bool GetBondDeal(const char* szCombBondKey, const char* szCompanyId,
                   MarketStreamInfo& record, time_t t = 0, uint32_t day = 0);
  bool GetBondDealBatch(const std::vector<BrokerKey>& brokerKeys,
                        std::vector<MarketStreamInfo>& records, time_t t = 0,
                        uint32_t day = 0);
  bool GetLastBondDeal(const std::vector<BrokerKey>& brokerKeys,
                       std::vector<MarketStreamInfo>& records, time_t t = 0,
                       uint32_t day = 0);

  // 用于过滤成交信息
  bool GetMarketStreamList(const MarkStreamListArg& arg, MSInfoList& mkList,
                           MSRecMap* mkRecordMap = NULL);

  // 用于获取排名靠前的成交信息
  bool GetTopRecords(const MarketStreamTopArg& arg, CMarketToprec& MarketInfo);

  // 用于获取成交数据的计数统计信息
  bool GetMarketInfo(const MarketStreamInfoArg& arg, CMarketInfoMap& infoMap);

 public:  // 导入成交信息
  void InsertCashData(xQBMarketStreamList_c* pLstdata, bool& ret);
  void InsertCFETSCashData(xQBMarketStreamList_c* pLstdata, uint32_t DealType,
                           bool& ret);
  RTDealList* GetList(DayType day);  // 外界不要使用,仅供CMarketStreamDebug
 protected:
  bool IsObjectValid() const;
  RTDealList* GetOrCreateList(DayType day);
  CMarketStream();
  virtual ~CMarketStream();

 public:
  static bool IsBondPassType(const CBondInfo& bond, MarktType type);
  static bool IsBondPassPage(const CBondInfo& bond, emMktStreamPage pageType);
  static int GetMarketInfoKey(int stat, int mktType, const CBondInfo& bond);
  static bool IsDealValid(const xQBMarketStreamUnit_c& msu, uint32_t& unDay,
                          kStreamType& type);
  static bool FilterDealList(xQBMarketStreamList_c* pLstdata,
                             std::vector<ParsedStreamInfo>& batch);
  static bool FilterCFETSDealList(xQBMarketStreamList_c* pLstdata,
                                  std::vector<ParsedStreamInfo>& batch,
                                  uint32_t DealType);
  static bool UpdateMarketInfoMap(const MarketStreamInfo& record, int mktype,
                                  int stattype, CMarketInfoMap& infoMap);
};
